package com.apestech.framework.sql.variable;

import com.apestech.framework.dictionary.modul.Table;
import com.apestech.framework.sql.SqlUtil;
import com.apestech.framework.sql.condition.ConditionMap;
import com.apestech.framework.sql.modul.FromList;
import com.apestech.framework.sql.modul.VarList;
import com.apestech.framework.xml.sql.SqlNodeVar;

import java.util.Locale;

/**
 * SQL含变量的语句段解析
 * @author hupo
 *
 */
public class SqlSection extends SqlUtil {
	
	private VarList plist;
	private int length=0;
	private int start=-1;
	private String varChar="";
	private String singleVar="";
	private FromList fromtab;
	private ConditionMap input;
	private String tab;
	private Object value;

	public SqlSection(FromList fromtab, ConditionMap input){
		this.fromtab=fromtab;
		this.input=input;
	}

	public SqlSection(FromList fromtab, String tab, Object value, ConditionMap input){
		this.fromtab=fromtab;
		this.tab=tab;
		this.value=value;
		this.input=input;
	}

	public SqlSection(FromList fromtab, String tab, ConditionMap input){
		this.fromtab=fromtab;
		this.tab=tab;
		this.input=input;
	}


	public SqlSection(FromList fromtab, Object value){
		this.fromtab=fromtab;
		this.value=value;
	}
	
	public void doVar(String text) throws Exception {
		text=finiSql(text);
		String t=text.trim();
		if(leftStr(text,1).equals("'") || countString(text,"'") / 2 !=0){
			if(!leftStr(t,6).equals("WHERE ") && !leftStr(t,7).equals("SELECT ")
					&& !leftStr(t,5).equals("FROM ") && !leftStr(t,4).equals("AND ")
					&& !leftStr(t,5).equals("LEFT ") && !leftStr(t,6).equals("RIGHT ") ){
				text=text.trim();
			}
		}
		this.plist=null;
		this.length=text.length();
		this.varChar="";
		this.singleVar="";
		this.plist=new VarList();
		this.plist.setText(text);
		getKeyList(text);
	}

	public void setTab(String tab) {
		this.tab = tab;
	}

	public void setValue(Object value) {
		this.value = value;
	}

	public Object getValue(int index) {
		if(this.plist.size()<index+1) return null;
		return this.plist.get(index).getValue();
	}

	public String getTable(int index) {
		if(this.plist.size()<index+1) return null;
		return this.plist.get(index).getTab();
	}

	public VarList getParam(){
		return this.plist;
	}
	
	public int getStart(int index){
		if(this.plist.size()<index+1) return -1;
		return this.plist.get(index).getStart();
	}
	
	public int getEnd(int index){
		if(this.plist.size()<index+1) return -1;
		return this.plist.get(index).getEnd();
	}
	
	public String getVar(int index){
		if(this.plist.size()<index+1) return "";
		return this.plist.get(index).getVar();
	}
	
	public String getSymbol(int index){
		if(this.plist.size()<index+1) return "";
		return this.plist.get(index).getSymbol();
	}
	
	public String[] getVarList(){
		return this.singleVar.split(";");
	}
	
	public String getSql(){
		return this.plist.getText();
	}

	private void getStartPos(String text, int pos){
		int pos1=text.indexOf(SqlNodeVar.getParamVar(), pos);
		int pos2=text.indexOf(SqlNodeVar.getValueVar(), pos);
		this.varChar="";
		this.start=-1;
		if((pos1>pos2 && pos2>=0)||(pos2>=0 && pos1<0)){
			this.varChar=SqlNodeVar.getValueVar();
			this.start=pos2;
		} else if((pos1<pos2 && pos1>=0)||(pos1>=0 && pos2<0)){
			this.varChar=SqlNodeVar.getParamVar();
			this.start=pos1;
		}
	}

	private String getAlais(String text){
		String alais=null;
		int pos1=-1;
		int pos2=-1;
		if(this.start>=0){
			for(int i=this.start; i>=0; i--){
				String s=text.substring(i, i+1);
				if(".".equals(s)){
					pos2=i;
				} else if(" ".equals(s) && pos2>=0){
					pos1=i+1;
					break;
				}
			}
		}

		if(pos2>pos1 && pos1>=0){
			alais=text.substring(pos1, pos2);
		}
		if(alais==null) return null;
		return alais.trim();
	}
	
	/**
	 * 获取字串中以前后缀方式对应的变量列表,示例 "#{变量}, ${变量}"
	 * @param text String 处理字串 处理字串
	 * @return
	 */
	private void getKeyList(String text) throws Exception {
		if(text==null){
			return;
		}
		this.singleVar="";
		int fin=0;
		while(fin<this.length){
			getStartPos(text,fin);
			int ist=this.start;
			int ien=text.indexOf("}", fin);
			if(ist>=0 && ien>=0){
				String s=text.substring(ist+2, ien);
				String table=tab;
				Object val=value;
				if(tab==null && fromtab!=null){
					if(fromtab.size()==1){
						table=fromtab.getTable(0);
					} else {
						String s1=getAlais(text);
						if(s1!=null && !"".equals(s1)){
							table=fromtab.getTableFromAlias(s1);
						}
					}
				}
				if(val==null && input!=null){
					if(s.equals("postId")){
						val=input.getPostId();
					} else {
						val=input.getFieldValue(s);
					}
				}
				String fieldValue=null;
				String notNull=null;
				String fieldType=null;
				String treeTable=null;
				String treeId=null;
				String treePId=null;
				Table dict=null;
				if(fromtab!=null && table!=null) dict=fromtab.getDictTable(table);
				if(dict!=null){
					String k=s;
					int pos=s.lastIndexOf(SqlNodeVar.getLISTVAR());
					if(pos>=0 && SqlNodeVar.getValueVar().equals(this.varChar)){
						k=s.substring(0, pos);
					}
					if(dict.getField().get(k)!=null){
						fieldType=dict.getTypeName(k);
						fieldValue=dict.getColumnDef(k);
						notNull=dict.getNotNull(k);
						treeTable=dict.getTreeTable(k);
						treeId=dict.getTreeId(k);
						treePId=dict.getTreePId(k);
					} else {
						table=null;
					}
				}

				this.plist.addInfo(ist, ien, s, this.varChar, table, val, fieldType, fieldValue, notNull, treeTable, treeId, treePId);
				fin=ien+1;
				if((";"+this.singleVar+";").indexOf(s)<0){
					if(!this.singleVar.equals("")){
						this.singleVar=this.singleVar+";";
					}
					this.singleVar=this.singleVar+s;
				}
			} else {
				fin=this.length;
			}
		}
	}

}
